﻿using EOS.Framework.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
// ===============================================================================
// XhtmlWriterTest.cs
// EOS Web Framework
// ===============================================================================
// Copyright (c) EOS Development Group. All rights reserved.
// ===============================================================================

namespace EOS.Framework.Web.Mvc.Tests
{
    using System;
    using EOS.Framework.Web.Mvc;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// This is a test class for XhtmlWriterTest and is intended
    /// to contain all XhtmlWriterTest Unit Tests
    /// </summary>
    [TestClass()]
    public class XhtmlWriterTest
    {
        /// <summary>
        /// Beginning of each output. Xml definition and xhtml DocType.
        /// </summary>
        private const string OutputStart = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
        
        private TestContext testContextInstance;

        /// <summary>
        /// Gets or sets the test context which provides
        /// information about and functionality for the current test run.
        /// </summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }       

        /// <summary>
        /// Tests the output of simple strings.
        /// </summary>
        [TestMethod()]
        public void WriteStringTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.WriteStartElement("Enclosing");
            writer.WriteString("Test");
            writer.WriteEndElement();

            string output = OutputStart + "<Enclosing xmlns=\"http://www.w3.org/1999/xhtml\">Test</Enclosing>";

            Assert.AreEqual(writer.Flush(), output, "Expected output not equals the actual output.");
        }

        /// <summary>
        /// Tests, if after flush cannot be written a string.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteStringAfterFlushTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.Flush();
            writer.WriteString("Test");
        }

        /// <summary>
        /// Test for WriteStartElement. 
        /// </summary>
        [TestMethod()]
        public void WriteStartElementTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.WriteStartElement("Test");
            writer.WriteEndElement();

            string output = OutputStart + "<Test xmlns=\"http://www.w3.org/1999/xhtml\"></Test>";

            Assert.AreEqual(writer.Flush(), output, "Expected output not equals the actual output.");
        }

        /// <summary>
        /// Test for WriteStartElement. Name must be a valid xml element name.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException), "Name must be a valid xml element name.")]
        public void WriteStartElementArgumentExceptionTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.WriteStartElement("A%234");
        }

        /// <summary>
        /// Test for WriteStartElement. All elements must be closed before Xml can be flushed.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteStartElementOnlyTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.WriteStartElement("Test");
            writer.Flush();
        }

        /// <summary>
        /// Test for WriteStartElement. Cannot call Write methode after Flush is called.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteStartElementAfterFlushTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.Flush();
            writer.WriteStartElement("Test");
        }

        /// <summary>
        /// A test for WriteRaw.
        /// </summary>
        [TestMethod()]
        public void WriteRawTest()
        {
            XhtmlWriter writer = new XhtmlWriter();
            writer.WriteRaw("Test");

            string output = OutputStart + "Test";

            Assert.AreEqual(writer.Flush(), output, "Expected output not equals the actual output.");
        }

        /// <summary>
        /// Tests, if a exception is thrown after call of the flush method.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteRawAfterFlushTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.Flush();
            writer.WriteRaw("Test");
        }

        /// <summary>
        /// Test for WriteEndElement.
        /// </summary>
        [TestMethod()]
        public void WriteNotEmptyXhtmlEndElementTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.WriteStartElement("script");
            writer.WriteEndElement();

            string output = OutputStart + "<script xmlns=\"http://www.w3.org/1999/xhtml\"></script>";

            Assert.AreEqual(writer.Flush(), output, "Expected output not equals the actual output.");
        }

        /// <summary>
        /// Test for WriteEndElement.
        /// </summary>
        [TestMethod()]
        public void WriteEmptyXhtmlEndElementTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.WriteStartElement("br");
            writer.WriteEndElement();

            string output = OutputStart + "<br xmlns=\"http://www.w3.org/1999/xhtml\" />";

            Assert.AreEqual(writer.Flush(), output, "Expected output not equals the actual output.");
        }

        /// <summary>
        /// Test for WriteEndElement. WriteStartElement must be called before WriteEndElement.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteEndElementBeforeStartElementTest()
        {
            XhtmlWriter writer = new XhtmlWriter();
            writer.WriteStartElement("Test");
            writer.WriteEndElement();
            writer.WriteEndElement();
        }

        /// <summary>
        /// Test for WriteEndElement. Method cannot called as first Method.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteEndElementFirstTest()
        {
            XhtmlWriter writer = new XhtmlWriter();
            writer.WriteEndElement();
        }

        /// <summary>
        /// Test for WriteEndElement. Method cannot be called after Flush.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteEndElementAfterFlushTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.WriteStartElement("Test");
            writer.Flush();
            writer.WriteEndElement();
        }

        /// <summary>
        /// Test for WriteAttribute.
        /// </summary>
        [TestMethod()]
        public void WriteAttributeTest()
        {
            XhtmlWriter writer = new XhtmlWriter();
            writer.WriteStartElement("Test");
            writer.WriteAttribute("Foo", "Bar");
            writer.WriteString("Test");
            writer.WriteEndElement();

            string output = OutputStart + "<Test Foo=\"Bar\" xmlns=\"http://www.w3.org/1999/xhtml\">Test</Test>";

            Assert.AreEqual(writer.Flush(), output, "Expected output not equals the actual output.");
        }

        /// <summary>
        /// Test for WriteAttribute. Attribute name must be valid.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException), "Invalid Name accepted.")]
        public void WriteAttributeNameArgumentExceptionTest()
        {
            XhtmlWriter writer = new XhtmlWriter(); 
            writer.WriteStartElement("Test");
            writer.WriteAttribute("Foo$", "Bar");
        }

        /// <summary>
        /// Test for WriteAttribute. Methode cannot be called after Flush.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void WriteAttributeAfterFlushTest()
        {
            XhtmlWriter writer = new XhtmlWriter();

            writer.Flush();
            writer.WriteAttribute("Test", "Test");
        }

        /// <summary>
        /// Test for Flush.
        /// </summary>
        [TestMethod()]
        public void FlushTest()
        {
            XhtmlWriter writer = new XhtmlWriter();
            writer.WriteStartElement("Test");
            writer.WriteAttribute("Foo", "Bar");
            writer.WriteString("Test");
            writer.WriteEndElement();

            string output = OutputStart + "<Test Foo=\"Bar\" xmlns=\"http://www.w3.org/1999/xhtml\">Test</Test>";

            Assert.AreEqual(writer.Flush(), output, "Expected output not equals the actual output.");
        }

        /// <summary>
        /// Test for Flush. Method cannot called twice.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void FlushTwiceTest()
        {
            XhtmlWriter writer = new XhtmlWriter();
            writer.Flush();
            writer.Flush();
        }

        /// <summary>
        /// Constructor test.
        /// </summary>
        [TestMethod()]
        public void XhtmlWriterConstructorTest()
        {
            XhtmlWriter target = new XhtmlWriter();
        }

        /// <summary>
        /// A test for XhtmlWriter Constructor
        /// </summary>
        [TestMethod()]
        public void XhtmlWriterConstructorTest1()
        {
            XhtmlWriter target = new XhtmlWriter();
            Assert.Inconclusive("TODO: Implement code to verify target");
        }
    }
}
